import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, Like } from 'typeorm';
import { ApiException } from '@main/common/exceptions/api.exception';
import GatherDistribute from '@main/entities/service/admin/gather/gather-distribute.entity';
import GatherDistributeParameter from '@main/entities/service/admin/gather/gather-distribute-parameter.entity';
import GatherDistributeParameterComputed from '@main/entities/service/admin/gather/gather-distribute-parameter-computed.entity';
import { SysOperationLogService } from '../../system/operationLog/operationLog.service';

@Injectable()
export class GatherDistributeService {
  constructor(
    @InjectRepository(GatherDistribute)
    private gatherDistributeRepository: Repository<GatherDistribute>,
    @InjectRepository(GatherDistributeParameter)
    private gatherDistributeParameterRepository: Repository<GatherDistributeParameter>,
    @InjectRepository(GatherDistributeParameterComputed)
    private gatherDistributeParameterComputedRepository: Repository<GatherDistributeParameterComputed>,
    private operationLogService: SysOperationLogService,
  ) {}

  async list() {
    return await this.gatherDistributeRepository.find();
  }

  /**
   * 罗列所有配置
   */
  async page(data) {
    const { pageSize, pageNum, entity = {} } = data;

    const { machineCode } = entity;

    return await this.gatherDistributeRepository.findAndCount({
      where: {
        machineCode: Like(`%${machineCode}%`),
      },
      order: {
        updateTime: 'DESC',
      },
      take: pageSize,
      skip: (pageNum - 1) * pageSize,
    });
  }

  /**
   * 新增
   */
  async add(data, user, mac, ip, syncHostSqlite) {
    const databaseOperationLogList = [];

    const gatherDistribute = await this.gatherDistributeRepository.insert({
      ...data,
      createName: user.nickName,
      createUserName: user.userName,
      updateName: user.nickName,
      updateUserName: user.userName,
    });
    databaseOperationLogList.push({
      type: 'add',
      dataType: 'obj',
      database: 'GatherDistribute',
      checkOnlyKeyList: [],
      data: gatherDistribute,
      whereObj: null,
      remark: `GatherDistribute表新增数据`,
    });

    await this.addDistributeParameter(data, user, mac, ip, syncHostSqlite);

    await this.operationLogService.add(
      {
        type: 'add',
        msg: `参数下发管理模块新增参数下发信息`,
        databaseOperationLogList,
        remark: `新增参数下发`,
        mac,
        ip,
        syncHostSqlite: isNaN(Number(syncHostSqlite)) ? 0 : Number(syncHostSqlite),
      },
      user
    );
  }

  async addDistributeParameter(data, user, mac, ip, syncHostSqlite) {
    const databaseOperationLogList = [];

    const { distributeList, machineCode } = data;

    if (distributeList && distributeList.length) {
      await this.gatherDistributeParameterRepository.delete({
        machineCode,
      });
      databaseOperationLogList.push({
        type: 'delete',
        dataType: 'array',
        database: 'GatherDistributeParameter',
        checkOnlyKeyList: [],
        data: null,
        whereObj: null,
        remark: `GatherDistributeParameter表删除参数配置`,
      });
      await this.operationLogService.add(
        {
          type: 'delete',
          msg: `参数下发管理参数配置删除参数配置`,
          databaseOperationLogList,
          remark: `删除参数下发信息`,
          mac,
          ip,
          syncHostSqlite: isNaN(Number(syncHostSqlite)) ? 0 : Number(syncHostSqlite),
        },
        user
      );
      const gatherDistributeParameter = await this.gatherDistributeParameterRepository.insert(distributeList);
      databaseOperationLogList.push({
        type: 'add',
        dataType: 'obj',
        database: 'GatherDistributeParameter',
        checkOnlyKeyList: [],
        data: gatherDistributeParameter,
        whereObj: null,
        remark: `GatherDistributeParameter表新增数据`,
      });
      await this.operationLogService.add(
        {
          type: 'add',
          msg: `参数下发管理参数配置增加参数配置`,
          databaseOperationLogList,
          remark: `新增参数配置`,
          mac,
          ip,
          syncHostSqlite: isNaN(Number(syncHostSqlite)) ? 0 : Number(syncHostSqlite),
        },
        user
      );

      await this.gatherDistributeParameterComputedRepository.delete({
        machineCode,
      });
      databaseOperationLogList.push({
        type: 'delete',
        dataType: 'array',
        database: 'GatherDistributeParameterComputed',
        checkOnlyKeyList: [],
        data: null,
        whereObj: null,
        remark: `GatherDistributeParameterComputed表删除计算公式`,
      });
      await this.operationLogService.add(
        {
          type: 'delete',
          msg: `参数下发管理参数配置计算公式删除计算公式`,
          databaseOperationLogList,
          remark: `删除计算公式`,
          mac,
          ip,
          syncHostSqlite: isNaN(Number(syncHostSqlite)) ? 0 : Number(syncHostSqlite),
        },
        user
      );

      for (let i = 0; i < distributeList.length; i++) {
        const { formulaList = [] } = distributeList[i];

        if (formulaList && formulaList.length) {
          await this.gatherDistributeParameterComputedRepository.insert(formulaList);
          databaseOperationLogList.push({
            type: 'add',
            dataType: 'obj',
            database: 'GatherDistributeParameterComputed',
            checkOnlyKeyList: [],
            data: gatherDistributeParameter,
            whereObj: null,
            remark: `GatherDistributeParameterComputed表新增数据`,
          });
          await this.operationLogService.add(
            {
              type: 'add',
              msg: `参数下发管理参数配置计算公式新增计算公式`,
              databaseOperationLogList,
              remark: `新增计算公式`,
              mac,
              ip,
              syncHostSqlite: isNaN(Number(syncHostSqlite)) ? 0 : Number(syncHostSqlite),
            },
            user
          );
        }
      }
    }
  }

  /**
   * 更新
   */
  async update(data, user, mac, ip, syncHostSqlite) {
    const databaseOperationLogList = [];

    const { id, remark } = data;

    await this.gatherDistributeRepository.update(
      { id },
      { remark, updateName: user.nickName, updateUserName: user.userName }
    );
    databaseOperationLogList.push({
      type: 'update',
      dataType: 'obj',
      database: 'GatherDistribute',
      checkOnlyKeyList: [],
      data: { remark, updateName: user.nickName, updateUserName: user.userName },
      whereObj: { id },
      remark: `GatherDistribute表更新连接信息`,
    });

    await this.addDistributeParameter(data, user, mac, ip, syncHostSqlite);

    await this.operationLogService.add(
      {
        type: 'update',
        msg: `参数下发管理模块更新参数下发信息`,
        databaseOperationLogList,
        remark: `更新参数下发信息`,
        mac,
        ip,
        syncHostSqlite: isNaN(Number(syncHostSqlite)) ? 0 : Number(syncHostSqlite),
      },
      user
    );
  }

  /**
   * 删除
   */
  async delete(idList, user, mac, ip, syncHostSqlite) {
    const databaseOperationLogList = [];

    for (let i = 0; i < idList.length; i++) {
      const obj = await this.gatherDistributeRepository.findOne({ where: { id: idList[i] } });

      if (obj) {
        const { machineCode } = obj;
        await this.gatherDistributeParameterRepository.delete({
          machineCode,
        });
        databaseOperationLogList.push({
          type: 'delete',
          dataType: 'array',
          database: 'GatherDistributeParameter',
          checkOnlyKeyList: [],
          data: null,
          whereObj: null,
          remark: `GatherDistributeParameter表删除参数配置`,
        });
        await this.operationLogService.add(
          {
            type: 'delete',
            msg: `参数下发管理参数配置删除参数配置`,
            databaseOperationLogList,
            remark: `删除参数下发信息`,
            mac,
            ip,
            syncHostSqlite: isNaN(Number(syncHostSqlite)) ? 0 : Number(syncHostSqlite),
          },
          user
        );
        await this.gatherDistributeParameterComputedRepository.delete({
          machineCode,
        });
        databaseOperationLogList.push({
          type: 'delete',
          dataType: 'array',
          database: 'GatherDistributeParameterComputed',
          checkOnlyKeyList: [],
          data: null,
          whereObj: null,
          remark: `GatherDistributeParameterComputed表删除计算公式`,
        });
        await this.operationLogService.add(
          {
            type: 'delete',
            msg: `参数下发管理参数配置计算公式删除计算公式`,
            databaseOperationLogList,
            remark: `删除计算公式`,
            mac,
            ip,
            syncHostSqlite: isNaN(Number(syncHostSqlite)) ? 0 : Number(syncHostSqlite),
          },
          user
        );
      }
    }

    await this.gatherDistributeRepository.delete(idList);

    databaseOperationLogList.push({
      type: 'delete',
      dataType: 'array',
      database: 'GatherDistribute',
      checkOnlyKeyList: [],
      data: null,
      whereObj: idList,
      remark: `GatherDistribute表删除参数下发信息`,
    });
    await this.operationLogService.add(
      {
        type: 'delete',
        msg: `参数下发管理模块删除参数下发信息`,
        databaseOperationLogList,
        remark: `删除参数下发信息`,
        mac,
        ip,
        syncHostSqlite: isNaN(Number(syncHostSqlite)) ? 0 : Number(syncHostSqlite),
      },
      user
    );
  }

  async isExistKey(machineCode: string) {
    const result = await this.gatherDistributeRepository.findOne({ where: { machineCode } });

    if (result) {
      throw new ApiException(10023);
    }
  }

  /**
   * 根据角色获取角色信息
   */
  async info(id) {
    const obj = await this.gatherDistributeRepository.findOne({
      where: { id },
    });

    return await this.distributeInfoFn(obj);
  }

  async infoByMachineCode(machineCode) {
    const obj = await this.gatherDistributeRepository.findOne({
      where: { machineCode },
    });

    return await this.distributeInfoFn(obj);
  }

  async distributeInfoFn(obj) {
    if (obj) {
      const { machineCode } = obj;

      const distributeList = await this.gatherDistributeParameterRepository.find({
        where: { machineCode },
        order: {
          proOrder: 'ASC',
        },
      });

      if (distributeList && distributeList.length) {
        // for (let i = 0; i < distributeList.length; i++) {
        //   const { parameterCode } = distributeList[i];

        //   const formulaList = await this.gatherDistributeParameterComputedRepository.find({
        //     where: { parameterCode, machineCode },
        //   });

        //   distributeList[i]['formulaList'] = formulaList;
        // }

        await Promise.all(
          distributeList.map(async (distribute: any) => {
            const formulaList = await this.gatherDistributeParameterComputedRepository.find({
              where: { parameterCode: distribute.parameterCode, machineCode },
            });
            distribute.formulaList = formulaList;
          })
        );
      }

      obj['distributeList'] = distributeList;

      return obj;
    }
  }
}
